package com.momo.demo06_indexQuery;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.junit.Test;

import com.momo.javabean.Article;
import com.momo.utils.DocumentUtils;
import com.momo.utils.LuceneUtils;

/**
 * @see 1、关键词查询
 * @see 2、查询所有的文档 重点
 * @see 3、范围查询
 * @see 4、通配符查询 重点
 * @see 5、短语查询
 * @see 6、Boolean查询 重点
 */
public class QueryTest {
    /**
     * 关键词查询 * 因为在创建Term对象的时候，没有分词器，所以这里的字母是区分大小写的 * Term构造函数的第二个参数指的是关键词，必须存在
     */
    @Test
    public void testTermQuery() throws Exception {
        Term term = new Term("title", "总冠军");
        Query query = new TermQuery(term);
        this.testSearchIndex(query);
    }

    /**
     * 查询所有的文档
     */
    @Test
    public void testAllQuery() throws Exception {
        Query query = new MatchAllDocsQuery();
        this.testSearchIndex(query);
    }

    /**
     * 通配符查询 说明： * 代表任意多个任意字符 ? 代表一个任意字符
     */
    @Test
    public void testWildCardQuery() throws Exception {
        Term term = new Term("title", "*总?军");
        Query query = new WildcardQuery(term);
        this.testSearchIndex(query);
    }

    /**
     * boolean查询 可以根据Occur的常量把好几个查询结合在一起
     */
    @Test
    public void testBooleanQuery() throws Exception {
        Term term = new Term("title", "总冠军");
        TermQuery termQuery = new TermQuery(term);

        Term term2 = new Term("content", "2?13");
        Query wildCardQuery = new WildcardQuery(term2);
        BooleanQuery query = new BooleanQuery();
        query.add(termQuery, Occur.SHOULD);// Occur.MUST必须有、Occur.MUST_NOT必须没有、Occur.SHOULD可以有
        query.add(wildCardQuery, Occur.SHOULD);
        this.testSearchIndex(query);
    }

    /**
     * 范围查询 查询id范围在5~15间的数据
     */
    @Test
    public void testRangeQuery() throws Exception {
        Query query = NumericRangeQuery.newLongRange("id", 5L, 15L, true, true);
        this.testSearchIndex(query);
    }

    /**
     * 所有的Term对象只能在同一个field中进行 如果两个以上大的关键词进行组合查询，得知道其中的位置(分词后的位置)
     */
    @Test
    public void testPharseQuery() throws Exception {
        Term term = new Term("title", "NBA总冠军");
        Term term2 = new Term("title", "NBA总冠军");
        PhraseQuery phraseQuery = new PhraseQuery();
        phraseQuery.add(term);
        phraseQuery.add(term2);
        this.testSearchIndex(phraseQuery);
    }

    // 公共输出方法
    private void testSearchIndex(Query query) throws Exception {
        IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
        TopDocs topDocs = indexSearcher.search(query, 50);
        int count = topDocs.totalHits;// 总的记录数
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        List<Article> articleList = new ArrayList<Article>();
        for (int i = 0; i < scoreDocs.length; i++) {
            int index = scoreDocs[i].doc;
            Document document = indexSearcher.doc(index);
            Article article = DocumentUtils.document2Article(document);
            articleList.add(article);
        }

        // 输入搜索出来的内容
        for (Article article : articleList) {
            System.out.println(article.getId());
            System.out.println(article.getTitle());
            System.out.println(article.getContent());
        }
    }

}
